package com.anolesoft.yr.mbus.code.service;

import com.anolesoft.yr.exception.ServiceException;
import com.anolesoft.yr.mbus.code.dto.CodeItemDTO;
import com.anolesoft.yr.mbus.code.dto.CodeItemRelDTO;
import com.anolesoft.yr.mbus.code.dto.CodeMainDTO;
import com.anolesoft.yr.mbus.code.service.gene.AbsoluteSequenceBuilder;
import com.anolesoft.yr.mbus.code.service.gene.GeneCodeService;
import com.anolesoft.yr.mbus.code.service.gene.RelativeSequenceBuilder;
import com.anolesoft.yr.mbus.code.service.gene.SequenceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Calendar;
import java.util.List;
import java.util.Optional;

/**
 * @author zhj
 * @date 2020/9/18 18:56
 */
@Component
public class CodeIncrementService {
//    @Autowired
//    public RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private CodeMainService codeMainService;

    @Autowired
    @Qualifier("AbsoluteSequenceBuilder")
    private SequenceBuilder absoluteSequenceBuilder;
    @Autowired
    @Qualifier("RelativeSequenceBuilder")
    private SequenceBuilder relativeSequenceBuilder;

    public String getValue(String codeName) {
        Optional<CodeMainDTO> optional = codeMainService.selectOneByCodeName(codeName);
        if (optional.isPresent()) {
            CodeMainDTO codeMainDTO = optional.get();
            String geneClass = codeMainDTO.getGeneClass();
            if (StringUtils.isEmpty(geneClass)) {
                List<CodeItemRelDTO> codeItemRels = codeMainDTO.getCodeItemRels();
                final StringBuilder builder = new StringBuilder();
                codeItemRels.forEach(codeItemRelDTO -> {
                    String itemCode = getItemCode(codeItemRelDTO, codeMainDTO);
                    builder.append(itemCode);
                });
                return builder.toString();
            } else {
                return GeneCodeService.execute(geneClass);
            }
        }
        throw new ServiceException("编号名称:" + codeName + " 不存在");
    }

    private String getItemCode(CodeItemRelDTO codeItemRelDTO, CodeMainDTO codeMainDTO) {
        CodeItemDTO codeItem = codeItemRelDTO.getCodeItem();
        if (StringUtils.isEmpty(codeItem)) {
            return "";
        }

        String format = codeItem.getItemFormat();
        if (format == null || "".equals(format.trim())) {
            format = "%1$s";
        }

        String retValue = "";
        Integer itemType = codeItem.getItemType();
        if (!StringUtils.isEmpty(itemType)) {
            String curValue = "";
            switch (itemType) {
                case FIXEDVALUE:
                    retValue = codeItem.getItemPlaceholder();
                    break;
                case ABSOLUTEVALUE:
                case RELATIVEVALUE:
                    curValue = this.getMaxId(codeItemRelDTO, codeMainDTO);
                    break;
                case CURRENTTIME:
                    retValue = String.format(format, Calendar.getInstance());
                    break;
                case JAVACLASS:
                    curValue = GeneCodeService.execute(codeItem.getItemGeneClass());
                    break;
                default:
                    break;
            }
            if (retValue == null || "".equals(retValue)) {
                retValue = String.format(format, curValue);
            }
        }
        String s =  this.dealLength(retValue, codeItem);
        return s;
    }

    private String getMaxId(final CodeItemRelDTO codeItemRel, final CodeMainDTO codeMain) {
        String indiId = getCodeBefore(codeItemRel, codeMain);
        Integer itemType = codeItemRel.getCodeItem().getItemType();
        switch (itemType) {
            case ABSOLUTEVALUE:
                return absoluteSequenceBuilder.getSequence(codeMain, codeItemRel.getCodeItem(), indiId);
            case RELATIVEVALUE:
                return relativeSequenceBuilder.getSequence(codeMain, codeItemRel.getCodeItem(), indiId);
            default:
                return "";
        }
    }

    private String getCodeBefore(final CodeItemRelDTO codeItemRel, final CodeMainDTO codeMainDTO) {
        String geneClass = codeMainDTO.getGeneClass();
        if (StringUtils.isEmpty(geneClass)) {
            List<CodeItemRelDTO> codeItemRels = codeMainDTO.getCodeItemRels();
            final StringBuilder builder = new StringBuilder();
            for (CodeItemRelDTO tempCodeItemRel : codeItemRels) {
                if (codeItemRel.getObjuid().equals(tempCodeItemRel.getObjuid())) {
                    break;
                }
                builder.append(getItemCode(tempCodeItemRel, codeMainDTO));
            }
            return builder.toString();
        } else {
            return GeneCodeService.execute(geneClass);
        }
    }

    private String dealLength(final String str,final CodeItemDTO codeItem) {
        int standardLen = 0;
        int strLen = 0;
        String standardPlaceholder = "0";
        if (codeItem.getItemLength() == null || str == null) {
            return str;
        }
        standardLen = codeItem.getItemLength();
        strLen = str.length();
        if (standardLen == strLen) {
            return str;
        }
        if (codeItem.getItemPlaceholder() != null && !"".equals(codeItem.getItemPlaceholder().trim())) {
            standardPlaceholder = codeItem.getItemPlaceholder();
            if (standardPlaceholder.length() > 1) {
                standardPlaceholder = standardPlaceholder.substring(0, 1);
            }
        }
        if (codeItem.getTrimAspect() == null || codeItem.getTrimAspect() == 1) {
            if (strLen > standardLen) {
                return str.substring(strLen - standardLen, strLen);
            }
            final StringBuilder bufferPh = new StringBuilder();
            for (int i = 0; i < standardLen - strLen; ++i) {
                bufferPh.append(standardPlaceholder);
            }
            bufferPh.append(str);
            return bufferPh.toString();
        } else {
            if (strLen > standardLen) {
                return str.substring(0, standardLen);
            }
            final StringBuilder bufferPh = new StringBuilder();
            for (int i = 0; i < standardLen - strLen; ++i) {
                bufferPh.append(standardPlaceholder);
            }
            return str + bufferPh.toString();
        }
    }

    private final static int FIXEDVALUE = 1;
    private final static int ABSOLUTEVALUE = 2;
    private final static int RELATIVEVALUE = 3;
    private final static int CURRENTTIME = 4;
    private final static int JAVACLASS = 100;

}
